package tool

import (
	"bytes"
	"encoding/binary"
	"encoding/hex"
	"fmt"
	"reflect"
	"runtime/debug"
	"time"
	"xlib/log"
)

//Insert 切片中插入元素
func Insert(slice interface{}, pos int, value interface{}) interface{} {
	v := reflect.ValueOf(slice)

	ne := reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(value)), 1, 1)
	ne.Index(0).Set(reflect.ValueOf(value))

	v = reflect.AppendSlice(v.Slice(0, pos), reflect.AppendSlice(ne, v.Slice(pos, v.Len())))

	return v.Interface()
}

//Remove 切片中删除元素
func Remove(slice interface{}, pos int) interface{} {
	v := reflect.ValueOf(slice)
	v = reflect.AppendSlice(v.Slice(0, pos), v.Slice(pos+1, v.Len()))

	return v.Interface()
}

//16进制数组转16进制字符串
func HexToHexStr(buf []byte) string {
	len := len(buf)
	str := ""
	for i := 0; i < len; i++ {
		if i == 0 {
			str = fmt.Sprintf("%02X", buf[i])
		} else {
			str += fmt.Sprintf(" %02X", buf[i])
		}
	}
	return str
}

//Convert 将字节数组按照指定字节序转换到指定结构中
func Convert(data []byte, order binary.ByteOrder, s interface{}) error {
	buf := new(bytes.Buffer)
	err := binary.Write(buf, order, data)
	if err != nil {
		log.Errorf("convert Write[%s] error:%s,type[%s:%s] stack:%s", hex.EncodeToString(data), err,
			reflect.TypeOf(s).Name(),
			reflect.TypeOf(s).String(),
			debug.Stack())
		return err
	}

	err = binary.Read(buf, order, s)
	if err != nil {
		log.Errorf("convert Read[%s] error:%s,type[%s:%s] stack:%s", hex.EncodeToString(data), err,
			reflect.TypeOf(s).Name(),
			reflect.TypeOf(s).String(),
			debug.Stack())
		return err
	}
	return nil
}

//ConvertOrder 转换数据的字节序: 大端 → 小端
func ConvertOrder(data uint32) uint32 {
	bs := make([]byte, 4)
	binary.BigEndian.PutUint32(bs, data)
	return binary.LittleEndian.Uint32(bs)
}

//FmtTime 格式化时间
func FmtTime(t [6]byte) time.Time {
	return time.Date(int(t[5])+2000, time.Month(t[4]), int(t[3]), int(t[2]), int(t[1]), int(t[0]), 0, time.Local)
}

//FmtBCDTime 格式化时间
func FmtBCDTime(t [6]byte) time.Time {
	return time.Date(BCDToInt(t[5])+2000, time.Month(BCDToInt(t[4])), BCDToInt(t[3]), BCDToInt(t[2]), BCDToInt(t[1]), BCDToInt(t[0]), 0, time.Local)
}

//BCDToInt BCD码转int
func BCDToInt(src byte) (dst int) {
	dst = int((src&0xF0)>>4)*10 + int(src&0x0F)
	return
}

//FmtPwd 格式化密码
func FmtPwd(pwd string, length int) []byte {
	if length == 0 || pwd == "" {
		return nil
	}

	var s string
	r := []rune(pwd)
	for len(r) < length {
		r = append(r, 'f')
	}
	s = string(r[:length])

	if data, err := hex.DecodeString(s); err == nil {
		return data
	}

	return nil
}

//ToBytes 将数据按照指定字节序转换成字节数组
func ToBytes(order binary.ByteOrder, v ...interface{}) []byte {
	if len(v) == 0 {
		return nil
	}

	buf := new(bytes.Buffer)
	for i := 0; i < len(v); i++ {
		if v[i] == nil {
			continue
		}
		err := binary.Write(buf, order, v[i])
		if err != nil {
			log.Error("to_bytes error:", err)
			return nil
		}
	}

	return buf.Bytes()
}
